import { ElementPropertyConfig } from '@farris/ide-property-panel';
import { cloneDeep, set } from 'lodash-es';
import FdToolBarComponent from '../../../command/toolbar/component/fd-toolbar';
import FdHeaderToolBarItemComponent from './fd-header-toolbar-item';
import { GlobalTool } from '../../../command/toolbar/component/globaltools/global-tool';
import { HeaderToolBarProp } from '../property/toolbar-property-config';
import { ComponentFactoryResolver, Injector } from '@angular/core';
import { BsModalService } from '@farris/ui-modal';
import { PageToolbarEditorComponent } from '../property/editor/page-toolbar-editor/page-toolbar-editor.component';
import { FormPropertyChangeObject } from '../../../../entity/property-change-entity';

export default class FdHeaderToolBarComponent extends FdToolBarComponent {
    globalTool: GlobalTool;
    private toolbar: any;

    /** 工具栏展示方式：modal弹窗/sidebar侧边栏 */
    showType: string;

    constructor(component: any, options: any) {
        super(component, options);
        this.viewModelId = this.parent.viewModelId;
        this.componentId = this.parent.componnentId;

        this.showType = this.options['showType'];

        const toolbar = this.options.designerHost.getService('DomService').module.toolbar;
        this.adaptOldControl();

        this.setToolbar(toolbar);
        this.customToolbarConfigs.push(
            {
                id: 'manageToolbar',
                title: '工具栏维护',
                icon: 'f-icon f-icon-home-setup',
                click: (e) => {
                    e.stopPropagation();

                    this.showPageToolbarEditor();
                }
            }
        );
    }

    /** 工具栏中没有按钮时，利用最小高度保证页面能选中工具栏，这样才能添加按钮 */
    getStyles(): string {
        return 'min-height: 30px;';
    }

    appendItems(items) {
        const toolbar = this.getToolbar();
        const modal = toolbar.configs[this.showType];
        if (modal[this.parent.id]) {
            items.forEach(itemId => {
                modal[this.parent.id].push(itemId);
            });
        }

        this.selectedId = items[items.length - 1];
        this.rebuild();
    }

    getToolbar() {
        return this.toolbar;
    }

    setToolbar(toolbar: any) {
        this.toolbar = toolbar;
    }

    reInit(component: any, showType: string) {
        this.component = component;
        this.items = component.items;

        this.showType = showType;
    }

    init() {
        this.components = [];

        const options = Object.assign({}, this.options, { childComponents: [], parent: this });
        this.toolBarItemList = this.items.map(item => {
            this.toolBarItem = new FdHeaderToolBarItemComponent(item, options, {
                isChildOfToolBar: true,
                viewModelId: this.viewModelId,
                componentId: this.componentId
            });
            return this.toolBarItem;
        });

        this.components = this.components.concat(this.toolBarItemList);
    }

    attach(element: HTMLElement): Promise<any> {
        const superAttach = super.attach(element);
        this.addEventListener(this.element, 'click', (event) => {
            event.stopPropagation();
            // 手动触发点击组件事件  展示属性面板
            this.parent.emit('componentClicked', {
                componentInstance: this
            });
        });
        return superAttach;
    }

    /**
     * 拖拽结束事件
     */
    dragEnd(e: any): void {
        super.dragEnd(e);

        const oldIndex = e.oldIndex;
        const newIndex = e.newIndex;

        // 修改全局按钮顺序
        if (oldIndex !== newIndex) {
            const items = this.toolbar.configs[this.showType][this.parent.id];
            const item = items[oldIndex];
            items.splice(oldIndex, 1);
            items.splice(newIndex, 0, item);
        }
    }
    /**
     * 组装属性面板配置数据
     */
    getPropertyConfig(): ElementPropertyConfig[] {
        const serviceHost = this.options && this.options.designerHost;
        const prop = new HeaderToolBarProp(serviceHost, this.viewModelId, this.componentId);
        const propertyConfig: ElementPropertyConfig[] = prop.getPropConfig(this.component);
        return propertyConfig;
    }

    onPropertyChanged(changeObject: FormPropertyChangeObject): void {
        super.onPropertyChanged(changeObject);
        if (changeObject.categoryId === 'toolbarPropsOnHeader') {
            // toolbar相关的变更要同步到header上
            this.parent.component[changeObject.propertyID] = changeObject.propertyValue;
            this.parent.onPropertyChanged(changeObject);
        }

    }
    /**
     * 同步单个按钮的全局配置
     * @param changeObject 变更集
     * @param buttonComponent 单个按钮json数据
     */
    onButtonPropertyChanged(changeObject: any, buttonComponent: any, parentItemId?: string): void {

        const buttonsInGlobal = this.toolbar.items[this.viewModelId];
        let buttonInGlobal;
        if (parentItemId) {
            const firstLevelItem = buttonsInGlobal.find(button => button.id === parentItemId);
            if (firstLevelItem && firstLevelItem.items && firstLevelItem.items.length) {
                buttonInGlobal = firstLevelItem.items.find(b => b.id === buttonComponent.id);
            }
        } else {
            buttonInGlobal = buttonsInGlobal.find(b => b.id === buttonComponent.id);
        }

        if (!buttonInGlobal) {
            return;
        }
        // 变更事件属性
        if (changeObject.categoryId === 'eventsEditor') {
            buttonInGlobal['click'] = buttonComponent['click'];
            return;
        }
        // 变更其他属性
        const path = changeObject.propertyPath ? `${changeObject.propertyPath}.${changeObject.propertyID}` : changeObject.propertyID;
        set(buttonInGlobal, path, changeObject.propertyValue);

        this.onPropertyChanged(changeObject);


    }
    rebuild(): Promise<any> {
        return this.parent.rebuild();
    }

    emit(eventName: string, fn: any) {
        return this.parent.emit(eventName, fn);
    }
    /**
     * 移除按钮
     * @param id 移除按钮id
     * @param parentItemId 移除按钮的父级按钮id，若移除的是一级按钮，则不需要传递
     */
    public removeToolBarItem(targetId: string, parentItemId?: string): void {

        const toolbar = this.getToolbar();
        const mesService = this.options.designerHost.getService('MessagerService');
        mesService.question('确定删除按钮？', () => {
            let targetIndex;
            let nextBtnId;
            // 获取当前显示模式下的按钮
            const allButtonIdsInShowType = toolbar.configs[this.showType];
            const buttonIds = allButtonIdsInShowType[this.parent.id];
            // 一级按钮：从当前控制中移除，但是全局按钮还是保留
            if (!parentItemId) {
                targetIndex = buttonIds.indexOf(targetId);
                if (!buttonIds || buttonIds.length === 0 || targetIndex < 0) {
                    return;
                }
                allButtonIdsInShowType[this.parent.id].splice(targetIndex, 1);

                nextBtnId = buttonIds[targetIndex];

            } else {
                // 二级按钮：从当前控件中移除，并且从全局按钮中移除
                const items = toolbar.items[this.viewModelId];
                const firstLevelItem = items.find(button => button.id === parentItemId);
                if (firstLevelItem) {
                    firstLevelItem.items = firstLevelItem.items || [];
                    targetIndex = firstLevelItem.items.findIndex(item => item.id === targetId);
                    firstLevelItem.items.splice(targetIndex, 1);

                    nextBtnId = firstLevelItem.items[targetIndex] ? firstLevelItem.items[targetIndex].id : null;
                }
            }


            // 自动选中下一个按钮
            this.setSelectedId(nextBtnId);

            if (!nextBtnId) {
                this.parent.emit('clearPropertyPanel');
            }
            this.rebuild();

            this.syncActions();
        });

    }

    /**
     * 新增按钮
     * @param item 新增按钮的元数据
     * @param parentItemId 新增按钮的父级按钮id，若新增的是一级按钮，则不需要传递
     */
    public appendItem(item: any, parentItemId?: string): void {
        const itemSchema = Object.assign({}, cloneDeep(item));
        itemSchema.id = `${itemSchema.id}-${Math.random().toString(36).slice(2, 6)}`;
        const toolbar = this.getToolbar();

        if (!toolbar.items[this.viewModelId]) {
            toolbar.items[this.viewModelId] = [];
        }
        if (!toolbar.configs[this.showType]) {
            toolbar.configs[this.showType] = {};
        }

        const items = toolbar.items[this.viewModelId];
        // 一级按钮
        if (!parentItemId) {
            items.push(itemSchema);
            const modal = toolbar.configs[this.showType];
            if (!modal[this.parent.id]) {
                modal[this.parent.id] = toolbar.configs[this.showType][this.parent.id] = [];
            }
            modal[this.parent.id].push(itemSchema.id);
        } else {
            // 二级按钮
            const firstLevelItem = items.find(button => button.id === parentItemId);
            if (firstLevelItem) {
                firstLevelItem.items = firstLevelItem.items || [];
                firstLevelItem.items.push(itemSchema);
            }
        }


        this.setSelectedId(itemSchema.id);
        this.rebuild();
    }

    /**
     * 复制按钮
     * @param id 被复制的按钮id
     */
    public cloneToolBarItem(id: string, parentItemId?: string): void {

        // 复制的新按钮的id
        let clonedToolBarItemId: string;

        if (parentItemId) {
            clonedToolBarItemId = this.cloneSecondLevelButton(id, parentItemId);
        } else {
            clonedToolBarItemId = this.cloneFirstLevelButton(id);
        }

        this.setSelectedId(clonedToolBarItemId);
        this.rebuild();
    }
    /**
     * 复制一级按钮
     * @param id 被复制按钮的id
     */
    private cloneFirstLevelButton(id: string) {
        const itemToCloneIndex = this.items.findIndex(item => item.id === id);
        const itemToClone = this.items[itemToCloneIndex];
        if (!itemToClone) {
            return;
        }
        const clonedToolBarItem = Object.assign(cloneDeep(itemToClone),
            {
                id: `${this.type}-cloned-${Math.random().toString(36).slice(2, 6)}`,
                click: null
            });


        delete clonedToolBarItem['disabled'];

        let itemsToClone = [];
        if (clonedToolBarItem.items && clonedToolBarItem.items.length) {
            itemsToClone = clonedToolBarItem.items.map(i => Object.assign(cloneDeep(i),
                {
                    id: `${this.type}-cloned-${Math.random().toString(36).slice(2, 6)}`,
                    click: null
                }));
        }
        clonedToolBarItem.items = itemsToClone;

        // 添加到被复制元素的后面
        const items = this.toolbar.items[this.viewModelId];
        items.push(clonedToolBarItem);
        const modal = this.toolbar.configs[this.showType];
        modal[this.parent.id].splice(itemToCloneIndex + 1, 0, clonedToolBarItem.id);

        return clonedToolBarItem.id;
    }

    /**
     * 复制二级按钮
     * @param id 被复制按钮的id
     * @param parentItemId 被复制按钮的父级按钮id
     */
    private cloneSecondLevelButton(id: string, parentItemId?: string) {
        const parentItem = this.items.find(item => item.id === parentItemId);
        const itemToCloneIndex = parentItem.items.findIndex(item => item.id === id);
        const itemToClone = parentItem.items[itemToCloneIndex];

        if (!itemToClone) {
            return;
        }

        const random = Math.random().toString(36).slice(2, 6);
        const clonedToolBarItem = Object.assign(cloneDeep(itemToClone),
            {
                id: `${this.type}-cloned-${random}`,
                click: null
            });

        delete clonedToolBarItem['disabled'];

        // 添加到被复制元素的后面
        const globalItems = this.toolbar.items[this.viewModelId];
        const firstLevelItem = globalItems.find(item => item.id === parentItemId);
        if (firstLevelItem) {
            firstLevelItem.items = firstLevelItem.items || [];
            firstLevelItem.items.splice(itemToCloneIndex + 1, 0, clonedToolBarItem);
        }


        return clonedToolBarItem.id;
    }

    /**
     * 二级按钮上移下移
     * @param targetBtnId 当前移动的二级按钮id
     * @param parentItemId 二级按钮所属的一级按钮id
     * @param action  上移/下移
     */
    moveUpAndDown(targetBtnId: string, parentItemId: string, action: string) {
        const parentItem = this.items.find(item => item.id === parentItemId);
        const index = parentItem.items.findIndex(i => i.id === targetBtnId);
        if (index < 0) {
            return;
        }


        const globalItems = this.toolbar.items[this.viewModelId];
        const firstLevelItem = globalItems.find(item => item.id === parentItemId);
        if (firstLevelItem) {
            firstLevelItem.items = firstLevelItem.items || [];

            const targetBtn = firstLevelItem.items[index];
            if (action === 'moveUp' && index > 0) {
                firstLevelItem.items.splice(index, 1);
                firstLevelItem.items.splice(index - 1, 0, targetBtn);

                this.rebuild();
            }

            if (action === 'moveDown' && index < firstLevelItem.items.length - 1) {
                firstLevelItem.items.splice(index, 1);
                firstLevelItem.items.splice(index + 1, 0, targetBtn);

                this.rebuild();
            }

        }
    }

    /**
     * 适配一些旧表单上的冗余按钮
     */
    private adaptOldControl() {
        const toolbar = this.options.designerHost.getService('DomService').module.toolbar;
        if (!toolbar || !toolbar.configs[this.showType] || !toolbar.configs[this.showType][this.parent.id]) {
            return;
        }

        const allItems = (toolbar.items || {})[this.viewModelId] as any[];
        const allItemIds = allItems.map(item => item.id);
        // 移除不存在的按钮id
        toolbar.configs[this.showType][this.parent.id] = toolbar.configs[this.showType][this.parent.id].filter(item => allItemIds.includes(item));
    }

    private showPageToolbarEditor() {
        // 动态创建相关的服务需要从designerHost中获取
        const serviceHost = this.options.designerHost;
        const resolver = serviceHost.getService('ComponentFactoryResolver') as ComponentFactoryResolver;
        const injector = serviceHost.getService('Injector') as Injector;
        const modalService = serviceHost.getService('ModalService') as BsModalService;

        const compFactory = resolver.resolveComponentFactory(PageToolbarEditorComponent);
        const compRef = compFactory.create(injector);
        const modalConfig = {
            title: '维护工具栏',
            width: 950,
            height: 600,
            showButtons: true,
            buttons: compRef.instance.modalFooter
        };
        compRef.instance.editorParams = {
            viewModelId: this.viewModelId,
            controlId: this.parent.component.id
        };
        const modalPanel = modalService.show(compRef, modalConfig);
        compRef.instance.closeModal.subscribe(() => {
            modalPanel.close();
        });
        compRef.instance.submitModal.subscribe(() => {
            this.parent.toolbarDatas = this.parent.assembleHeaderToolbar();
            this.parent.redraw();
            modalPanel.close();
        });
    }
}
